package com.freedom.auth.infrastructure.extension.refresh;

import cn.hutool.core.lang.Assert;
import com.freedom.auth.domain.service.member.MemberUserDetailsServiceImpl;
import com.freedom.auth.infrastructure.enums.AuthenticationIdentityEnum;
import com.freedom.auth.infrastructure.utils.AuthUtil;
import com.freedom.common.core.base.IBaseEnum;
import com.freedom.common.core.constant.SecurityConstant;
import com.freedom.common.core.enums.AuthResultCodeEnum;
import com.freedom.common.core.enums.ResultCodeEnum;
import com.freedom.common.framework.exception.ServiceException;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;

import java.util.Map;
import java.util.Objects;

/**
 * 刷新token再次认证 UserDetailsService
 *
 */
@NoArgsConstructor
public class PreAuthenticatedUserDetailsService<T extends Authentication> implements AuthenticationUserDetailsService<T>, InitializingBean {

    /**
     * 客户端ID和用户服务 UserDetailService 的映射
     *
     * @see com.freedom.auth.infrastructure.config.AuthorizationServerConfig#tokenServices(AuthorizationServerEndpointsConfigurer)
     */
    private Map<String, UserDetailsService> userDetailsServiceMap;

    public PreAuthenticatedUserDetailsService(Map<String, UserDetailsService> userDetailsServiceMap) {
        Assert.notNull(userDetailsServiceMap, () -> new ServiceException(ResultCodeEnum.PARAM_ERROR));
        this.userDetailsServiceMap = userDetailsServiceMap;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(this.userDetailsServiceMap, () -> new ServiceException(ResultCodeEnum.PARAM_ERROR));
    }

    /**
     * 重写PreAuthenticatedAuthenticationProvider 的 preAuthenticatedUserDetailsService 属性，可根据客户端和认证方式选择用户服务 UserDetailService 获取用户信息 UserDetail
     *
     * @param authentication
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException {
        String clientId = AuthUtil.getAuthClientId();
        AuthenticationIdentityEnum authenticationIdentityEnum = IBaseEnum.getEnumByValue(AuthUtil.getAuthenticationIdentity(), AuthenticationIdentityEnum.class);
        UserDetailsService userDetailsService = userDetailsServiceMap.get(clientId);
        if (clientId.equals(SecurityConstant.APP_CLIENT_ID)) {
            // 移动端的用户体系是会员，认证方式是通过手机号 mobile 认证
            MemberUserDetailsServiceImpl memberUserDetailsService = (MemberUserDetailsServiceImpl) userDetailsService;
            switch (authenticationIdentityEnum) {
                case MOBILE:
                    return memberUserDetailsService.loadUserByMobile(authentication.getName());
                case EMAIL:
                    return memberUserDetailsService.loadUserByEmail(authentication.getName());
                default:
                    throw new ServiceException(AuthResultCodeEnum.AUTH_WAY_ERROR);
            }
        } else if (clientId.equals(SecurityConstant.WEBAPP_CLIENT_ID)) {
            // 小程序的用户体系是会员，认证方式是通过微信三方标识 openid 认证
            MemberUserDetailsServiceImpl memberUserDetailsService = (MemberUserDetailsServiceImpl) userDetailsService;
            switch (authenticationIdentityEnum) {
                case OPENID:
                    return memberUserDetailsService.loadUserByOpenId(authentication.getName());
                case USERNAME:
                    return memberUserDetailsService.loadUserByUsername(authentication.getName());
                default:
                    throw new ServiceException(AuthResultCodeEnum.AUTH_WAY_ERROR);
            }
        } else if (clientId.equals(SecurityConstant.ADMIN_CLIENT_ID)) {
            // 管理系统的用户体系是系统用户，认证方式通过用户名 username 认证
            if (Objects.requireNonNull(authenticationIdentityEnum) == AuthenticationIdentityEnum.USERNAME) {
                return userDetailsService.loadUserByUsername(authentication.getName());
            }
        } else if (clientId.equals(SecurityConstant.SUPPLIER_CLIENT_ID)) {
            // 供应商系统的用户体系是系统用户，认证方式通过手机号 mobile 认证
            MemberUserDetailsServiceImpl memberUserDetailsService = (MemberUserDetailsServiceImpl) userDetailsService;
            if (Objects.requireNonNull(authenticationIdentityEnum) == AuthenticationIdentityEnum.MOBILE) {
                return memberUserDetailsService.loadStoreUserByMobile(authentication.getName());
            }
        }
        throw new ServiceException(AuthResultCodeEnum.AUTH_WAY_ERROR);
    }
}
